package com.jbm.core.common;

import com.jbm.core.common.ResponseRecvCallback.ResponseRecvCallback;
import com.jbm.core.iface.IAcross;
import com.jbm.core.pb.PBIAcross;
import org.apache.mina.core.buffer.IoBuffer;
import org.apache.mina.core.future.WriteFuture;

import java.lang.Object;
import java.nio.charset.Charset;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;

import org.apache.mina.core.session.IoSession;

/**
 * Created by root on 16-10-16.
 */
public class P2PDialog implements Life
{
	protected int m_retry;
	protected int m_timeout;
	protected int m_status;
	protected Resource m_resource;
	protected ResKey m_lifename;
	protected Object[] m_param;
	protected RandR m_request;
	protected long m_borntimems;
	protected long m_lasttryms;
	protected int m_trytimes;
	protected boolean m_isasked;
	protected boolean m_resend;

	protected Object m_exinfo;
	protected boolean m_isfirst;

	protected IoSessionShell m_iosession;

	protected ResponseRecvCallback m_rrcallback;

	protected IAcross m_content;

	protected final Object m_response_mutex = new Object();

	public P2PDialog( )
	{
		m_status = life_status_newlife;
		m_isasked = false;
		m_resend = true;
		m_content = null;
		m_isfirst = true;
	}

	public P2PDialog(int msg_len )
	{
		this();

		this.m_message = new ArrayBlockingQueue(msg_len);
	}

	public void Bind_IoSession ( IoSessionShell session )
	{
		m_iosession = session;
	}

	public void Bind_Request ( RandR request )
	{
		m_request = request;
	}

	public void Bind_Exinfo ( Object exinfo )
	{
		m_exinfo = exinfo;
	}
	public void Bind_Isfirst ( boolean isfirst )
	{
		m_isfirst = isfirst;
	}

	public void Bind_RRCallback (ResponseRecvCallback rrcallback)
	{
		m_rrcallback = rrcallback;
	}

	public void setM_content(IAcross content)
	{
		m_content = content;
	}

	@Override
	public void Born(int retry, int timeout)
	{
		this.m_borntimems = System.currentTimeMillis();
		this.m_lasttryms = this.m_borntimems;
		this.m_retry = retry;
		this.m_timeout = timeout;
		this.m_trytimes = 0;
	}

	@Override
	public boolean AmILiving()
	{
		return true;
	}

	@Override
	public boolean IamLiving()
	{
		return true;
	}

	@Override
	public boolean RuLiving()
	{
		return true;
	}

	@Override
	public boolean RuLivingWell()
	{
		return true;
	}

	@Override
	public boolean Wakeup(Object... args)
	{
		boolean send = false;

		if ( !m_isasked )
		{
			long cms = System.currentTimeMillis();

			if ( m_lasttryms + m_timeout < cms )
			{
				m_lasttryms = cms;
				m_trytimes++;
				send = true;
			}

			if ( m_trytimes <= m_retry )
			{
				if (send&&m_resend)
				{
					if ( m_rrcallback != null )
						m_rrcallback.PushResponse(m_borntimems,cms,(PBIAcross.IAcross)m_request.GetCore(),m_content,null,m_exinfo,m_isfirst);

//					m_iosession.write(m_request.GetCore());
				}
			}else
			{
				Put(m_request.BuildTimeoutResponse());
				ReleaseFromPool();
			}
		}

		return true;
	}

	@Override
	public int IsLast ( Object... args )
	{
		if ( this.m_request == null )
			return 1;

		return this.m_request.islastresult((PBIAcross.IAcross)args[0]);
	}

	@Override
	public boolean Die()
	{
		m_resend = false;
		m_trytimes = 0;
		return true;
	}

	@Override
	public boolean BindParameter(Object... param)
	{
		this.m_param = param;
		return true;
	}

	@Override
	public Object GetParameter(int index)
	{
		return this.m_param[index];
	}

	@Override
	public boolean BindLifeName(ResKey key)
	{
		this.m_lifename = key;
		return true;
	}

	@Override
	public ResKey GetLifeName()
	{
		return this.m_lifename;
	}

	@Override
	public boolean SetStatus(int status)
	{
		return true;
	}

	@Override
	public int GetStatus()
	{
		return this.m_status;
	}

	@Override
	public int GetOverTime()
	{
		return this.m_timeout;
	}

	@Override
	public boolean ReleaseFromPool ( )
	{
		if ( m_resource != null )
			return m_resource.Drop(m_lifename);
		else
			return false;
	}

	@Override
	public boolean BindPool ( Resource resource )
	{
		this.m_resource = resource;
		return true;
	}

	@Override
	public Object[] GetUniqueIndex ()
	{
		return null;
	}

	@Override
	public void SetUniqueIndex ( Object... uniqueidx )
	{
	}

	protected BlockingQueue m_message;

	public boolean Put ( Object msg )
	{
		try
		{
			synchronized (m_response_mutex)
			{
				if (m_rrcallback != null)
					m_rrcallback.PushResponse(m_borntimems, System.currentTimeMillis(), (PBIAcross.IAcross) m_request.GetCore(), m_content,(PBIAcross.IAcross) msg,m_exinfo,m_isfirst);
				m_message.put(msg);
				m_isasked = true;
			}
		}catch (Exception e)
		{
			return false;
		}

		return true;
	}

	public Object Get ( )
	{
		try
		{
			return m_message.take();
		}catch (Exception e)
		{
			return null;
		}
	}
}
